package labox.innovation.db;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javolution.util.FastList;
import labox.innovation.config.Config;
import labox.innovation.db.core.HeapByteBuffer;
import labox.innovation.db.core.SqlData;
import labox.innovation.db.manager.DBConnetionStateManager;
import labox.innovation.db.proxy.ConnectionProxy;
import labox.innovation.db.proxy.PreparedStatementProxy;
import labox.innovation.db.util.DbUtil;
import labox.innovation.db.util.SqlDataIdFactory;
import labox.innovation.gameserver.datatables.ItemTable;
import labox.innovation.gameserver.model.L2ItemInstance;
import labox.innovation.gameserver.model.L2ItemInstance.ItemLocation;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.itemcontainer.ItemContainer;
import labox.innovation.gameserver.model.itemcontainer.PcInventory;
import labox.innovation.gameserver.model.itemcontainer.PcWarehouse;
import labox.innovation.gameserver.model.itemcontainer.Warehouse;
import labox.innovation.gameserver.templates.item.ItemIdentifyManage;
import labox.innovation.gameserver.templates.item.ItemRandAttribute;
import labox.innovation.gameserver.templates.item.ItemStarBouns;
import labox.innovation.gameserver.templates.item.L2Item;
import labox.innovation.gameserver.templates.item.ItemBouns.ItemBounsType;
import labox.innovation.gameserver.templates.item.ItemIdentifyManage.IdentifyBouns;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ItemsDb {
	public static final Logger _log = LoggerFactory.getLogger(ItemsDb.class.getName());
	private static ItemLocation[] itemLocations = ItemLocation.values();
	/**
	 * ���ر���,�ֿ�
	 */
	private static final String LOAD_ITMES = "select charId,details,capacity from items where charId=?";
	/**
	 * ���汳��,�ֿ�
	 */
	private static final String SAVE_ITMES = "replace into items (charId,details,sliver,capacity) values (?,?,?,?)";
	/**
	 * ɾ���ɫ����ֿ�
	 */
	public static final String PHYSICAL_DELETE_ITEMS_BY_OWNERID = "delete from items where charId=?";

	/**
	 * ���ر���ֿ�
	 * 
	 * @param charId ���ID
	 * @param baseLocation ����
	 * @param equipLocation װ��
	 * @return
	 */
	public static List<L2ItemInstance> restoreContainer(long charId, ItemContainer container) {
		List<L2ItemInstance> inventory = new FastList<L2ItemInstance>();
		List<L2ItemInstance> warehouse = new FastList<L2ItemInstance>();
		HeapByteBuffer _buf = HeapByteBuffer.newInstance();
		Integer capacity = Warehouse.INITIALIZE_NUM;
		ConnectionProxy con = null;
		PreparedStatementProxy ptmt = null;
		ResultSet rest = null;
		try {
			if (DBConnetionStateManager.getDbState()) {
				con = ConnectionProxy.newInstance();
				if (con != null)
					ptmt = con.prepareStatement(LOAD_ITMES);
				if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, ptmt))
					return null;
				ptmt.setLong(1, charId);
				rest = ptmt.executeQuery();
				if (rest == null)
					return null;
				long _charid;
				L2ItemInstance inst = null;
				byte[] bytes;
				while (rest.next()) {
					_buf.clear();
					bytes = rest.getBytes(2);
					_charid = rest.getLong(1);
					_buf.write(bytes, 0, bytes.length);
					_buf.flip();
					// ����
					int loctype = _buf.readByte();
					if (loctype == 1) {
						int size = _buf.readByte();
						for (int i = 0; i < size; i++) {
							// ��ȡ��������
							inst = commonReadItem(_buf, _charid);
							if (inst != null) {
								inventory.add(inst);
							}
						}
					}
					// �ֿ�
					int _loctype = _buf.readByte();
					if (_loctype == 2) {
						int _size = _buf.readByte();
						for (int i = 0; i < _size; i++) {
							inst = commonReadItem(_buf, _charid);
							if (inst != null) {
								warehouse.add(inst);
							}
						}
					}
					capacity = rest.getInt(3);
				}
			}

		} catch (Exception e) {
			_log.error("Error ItemsDb  retoreContainer:charId="+charId, Config.SERVER_ID, e);
			e.printStackTrace();
		} finally {
			HeapByteBuffer.recycle(_buf);
			try {
				rest.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
			if (ptmt != null)
				ptmt.close();
			if (con != null)
				con.close();
		}
		if (container.getBaseLocation().name().equals("INVENTORY"))
			return inventory;
		else if (container.getBaseLocation().name().equals("WAREHOUSE")) {
			if (capacity != null)
				container.setMaxCurrentSoltNums(capacity);
			return warehouse;
		} else {
			return null;
		}

	}

	/***
	 * ���±���Ͳֿ�
	 * 
	 * @param _items ��Ʒ�б�
	 * @param charId ���ID
	 * @throws SQLException
	 */
	public static void updateitemContainer(PcInventory inventory, PcWarehouse warehouse, long objectId) {
		HeapByteBuffer _buf = HeapByteBuffer.newInstance();
		_buf.clear();
		int _wealth = 0;
		_buf.writeByte(1);// ����
		_wealth = commmonStoreContainer(inventory, _buf, _wealth);
		_buf.writeByte(2);// �ֿ�
		if (warehouse != null) {
			commmonStoreContainer(warehouse, _buf, -1);// �ֿⲻװ��
		} else {
			_buf.writeByte(0);
		}
		_buf.flip();

		Object[] params = null;
		SqlData data = null;
		ConnectionProxy con = null;
		PreparedStatementProxy state = null;
		try {
			if (DBConnetionStateManager.getDbState()) {
				con = ConnectionProxy.newInstance();
				if (con != null)
					state = con.prepareStatement(SAVE_ITMES);
				if (!DbUtil.isDbNormal(DBConnetionStateManager.getDbState(), con, state)) {
					params = new Object[] { objectId, _buf, _wealth, warehouse._maxCurrentSoltNums };
					data = new SqlData(SqlDataIdFactory.createSqlId("items", objectId), SAVE_ITMES, params);
					DBConnetionStateManager.addDbTask(data);
				} else {
					state.setLong(1, objectId);
					state.setBinaryStream(2, _buf, _buf.limit());
					state.setInt(3, _wealth);
					state.setInt(4, warehouse._maxCurrentSoltNums);
					int rs = state.executeUpdate();
					if (rs != PreparedStatementProxy.NETWORKDISCONNECTION) {
						HeapByteBuffer.recycle(_buf);
					} else {
						params = new Object[] { objectId, _buf, _wealth, warehouse._maxCurrentSoltNums };
						data = new SqlData(SqlDataIdFactory.createSqlId("items", objectId), SAVE_ITMES, params);
						DBConnetionStateManager.addDbTask(data);
					}
				}

			} else {
				params = new Object[] { objectId, _buf, _wealth, warehouse._maxCurrentSoltNums };
				data = new SqlData(SqlDataIdFactory.createSqlId("items", objectId), SAVE_ITMES, params);
				DBConnetionStateManager.addDbTask(data);
			}
		} catch (SQLException e) {
			_log.error("save inventory warehouse to db error: charId="+objectId, Config.SERVER_ID, e);
		} finally {
			if (state != null)
				state.close();
			if (con != null)
				con.close();
		}

	}

	/***
	 * ������������ֿ� ,���������
	 * 
	 * @param container
	 * @param _buf
	 * @param _wealth
	 * @return
	 */
	public static int commmonStoreContainer(ItemContainer container, HeapByteBuffer _buf, int _wealth) {

		_buf.writeByte(container.getItems().length);
		// �Ƹ����а�Ϊ ���ĺ���Ʊ֮��
		for (L2ItemInstance item : container.getItems()) {
			if (_wealth > -1) {
				if (item.getItemId() == PcInventory.MONEY_SLIVER_ID) {
					_wealth += item.getCount();
				}
				if (item.getItemId() == PcInventory.MONEY_NOTE_ID) {
					_wealth += item.getCount();
				}

			}
			// д��ݿ�
			commonWriteItem(item, _buf);
		}
		return _wealth;
	}

	/***
	 * ��ȡ��ݿ���Ʒ�Ĺ�������
	 * 
	 * @param _buf
	 * @param _charid
	 * @return
	 */
	public static L2ItemInstance commonReadItem(HeapByteBuffer _buf, long _charid) {
		long objectId = _buf.readLong(); // 1Ψһֵ
		int item_id = _buf.readInt();// 2��ƷID
		L2Item item = ItemTable.getInstance().getTemplate(item_id);// 2
		if (item == null) {
			return null;
		}
		L2ItemInstance inst = new L2ItemInstance(objectId, item);// 1
		int count = _buf.readInt();// // 3 ����
		long time = _buf.readLong();// 4 ʱ��
		boolean decrease = _buf.readByte() != 0;// 5
		ItemLocation loc = itemLocations[_buf.readByte()];// 6
		int loc_data = _buf.readByte();// 7
		int endurance = _buf.readInt();// 8
		boolean isBinding = _buf.readByte() != 0;// 9
		int starLevel = _buf.readInt();// 10
		int holeNums = _buf.readInt();// 11
		int itemGrade = _buf.readInt();// 12
		ItemRandAttribute itemRandAttribute = new ItemRandAttribute();// ��������
		int _randsize = _buf.readByte();
		if (_randsize > 0) { // 13
			for (int j = 0; j < _randsize; j++) {
				int key = _buf.readInt();
				int value = _buf.readInt();
				itemRandAttribute.addItemAttriFromDB(key, value);
			}
			inst.addItemBounsByDb(itemRandAttribute);
		}
		int identifyBounsjian = _buf.readInt();// 14
		int identifyBounsmin = _buf.readInt();// 15
		boolean isIdentify = _buf.readByte() != 0;// 16
		boolean isInscribe = _buf.readByte() != 0;// 17
		inst.setOwnerId(_charid);// 0
		inst.setCount(count);// 3
		inst.set_time(time);// 4
		inst.setCountDecrease(decrease);// 5
		inst.set_loc(loc);// 6
		inst.set_locData(loc_data);// 7
		inst.setEndurance(endurance);// 8
		inst.setBinding(isBinding);// 9
		inst.setStarLvl(starLevel);// 10
		inst.setHoleNum(holeNums);// 11
		inst.setItemGrade(itemGrade);// 12
		if (starLevel > 0) {
			ItemStarBouns itemStarBouns = new ItemStarBouns();
			itemStarBouns.setStarLvl(starLevel);
			itemStarBouns.update(inst);
			inst.addItemBounsByDb(itemStarBouns);// 14
		}
		if (identifyBounsjian > -1) {
			IdentifyBouns identifyBounsJian = new IdentifyBouns(item._attributs, identifyBounsjian, ItemIdentifyManage.IDENTIFY_ID);// ��
			inst.addItemBounsByDb(identifyBounsJian);// 15
		}
		if (identifyBounsmin > -1) {
			IdentifyBouns identifyBounsMin = new IdentifyBouns(item._attributs, identifyBounsmin, ItemIdentifyManage.INSCRIBE_ID);// ����
			inst.addItemBounsByDb(identifyBounsMin);
		}
		inst.setIdentify(isIdentify);// 16
		inst.setInscribe(isInscribe);// 17
		inst.setStoreExp(_buf.readInt());// 18���ô洢����
		return inst;
	}

	/****
	 * ��д��ݿ���Ʒ�Ĺ�������
	 * 
	 * @param item
	 * @param _buf
	 */
	public static void commonWriteItem(L2ItemInstance item, HeapByteBuffer _buf) {
		_buf.writeLong(item.getObjectId());// 1
		_buf.writeInt(item.getItemId());// 2
		_buf.writeInt(item.getCount());// 3
		_buf.writeLong(item.get_time());// 4
		_buf.writeByte(item.getCountDecrease() ? 1 : 0);// 5
		_buf.writeByte(item.get_loc().ordinal());// 6
		_buf.writeByte(item.get_locData());// 7
		_buf.writeInt(item.getEndurance());// 8
		_buf.writeByte(item.isBinding() ? 1 : 0);// 9
		_buf.writeInt(item.getStarLvl());// 10
		_buf.writeInt(item.getHoleNums());// 11
		_buf.writeInt(item.getItemGrade());// 12
		ItemRandAttribute randAttribute = null;
		if (item.getItemBouns() != null)//
			randAttribute = (ItemRandAttribute) item.getItemBouns(1);// 1Ϊ�������ϵͳ
		if (randAttribute != null) {
			Map<Integer, Integer> _collection = randAttribute.getAttriMap();// ��ȡ�������MAP��
			_buf.writeByte(_collection.size());// 13
			Iterator<Map.Entry<Integer, Integer>> it = _collection.entrySet().iterator();
			while (it.hasNext()) {
				Map.Entry<Integer, Integer> mapEn = it.next();
				int key = mapEn.getKey();
				int value = mapEn.getValue();
				_buf.writeInt(key);
				_buf.writeInt(value);
			}
		} else {
			_buf.writeByte(0);// ���������Բ����� ,��0ֵ
		}
		IdentifyBouns identifyBounjian = null;
		if (item.getItemBouns() != null)
			identifyBounjian = (IdentifyBouns) item.getItemBouns(ItemBounsType.IDENTIFY_BOUNS.ordinal());// ��ʼ����ϵͳ
		if (identifyBounjian != null) {
			_buf.writeInt(identifyBounjian.getBounsRate());// 14
		} else {
			_buf.writeInt(-1); // ����ϵͳ�����ڣ���-1ֵ
		}
		IdentifyBouns identifyBounsmin = null;
		if (item.getItemBouns() != null)
			identifyBounsmin = (IdentifyBouns) item.getItemBouns(ItemBounsType.INSCRIBE_BOUNS.ordinal());// ��ʼ����ϵͳ
		if (identifyBounsmin != null) {
			_buf.writeInt(identifyBounsmin.getBounsRate());// 15
		} else {
			_buf.writeInt(-1); // ������ϵͳ�����ڣ���-1ֵ
		}
		_buf.writeByte(item.isIdentify() ? 1 : 0);// 16//�Ƿ��
		_buf.writeByte(item.isInscribe() ? 1 : 0);// 17//�Ƿ����
		_buf.writeInt(item.getStoreExp());// 18�洢����ֵ
	}
}
